﻿using System;

using System.Runtime.InteropServices;

namespace Eflong.Structure
{
    [StructLayout( LayoutKind.Sequential )]
    public struct MonUnitData
    {
        private const int SIZE_MONUNITID = 9;

        [MarshalAs( UnmanagedType.ByValTStr , SizeConst = SIZE_MONUNITID )]
        public string m_szId;

        public SystemTime m_stData;
        public SystemTime m_stStateChange;
        public byte m_nState;
        public float m_fValue;

        public static int Size( )
        {
            return 48;
        }

        public byte[ ] GetByteArray( )
        {
            int length = Marshal.SizeOf( this );
            byte[ ] ba = new byte[ length ];

            IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement( ba , 0 );
            Marshal.StructureToPtr( this , ptr , true );

            return ba;
        }

        public static MonUnitData ConverFromByteArray( byte[ ] ba , ref int pos )
        {
            MonUnitData data = StructConvert.PtrToStruct<MonUnitData>( ba , ref pos );
            return data;
        }

        public static MonUnitData ConverFromByteArray( IntPtr intPtr , ref int pos )
        {
            MonUnitData data = StructConvert.PtrToStruct<MonUnitData>( intPtr , ref pos );
            return data;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct MonUnitDataEx
    {
        private const int SIZE_MONUNITID_EX = 9;

        [MarshalAs( UnmanagedType.ByValTStr , SizeConst = SIZE_MONUNITID_EX )]
        public string m_szId;

        public SystemTime m_stData;
        public SystemTime m_stStateChange;
        public byte m_nState;
        public float m_fValue;

        public static int Size( )
        {
            return 48;
        }

        public byte[ ] GetByteArray( )
        {
            int length = Marshal.SizeOf( this );
            byte[ ] ba = new byte[ length ];

            IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement( ba , 0 );
            Marshal.StructureToPtr( this , ptr , true );

            return ba;
        }

        public static MonUnitDataEx ConverFromByteArray( byte[ ] ba , ref int pos )
        {
            MonUnitDataEx data = StructConvert.PtrToStruct<MonUnitDataEx>( ba , ref pos );
            return data;
        }

        public static MonUnitDataEx ConverFromByteArray( IntPtr intPtr , ref int pos )
        {
            MonUnitDataEx data = StructConvert.PtrToStruct<MonUnitDataEx>( intPtr , ref pos );
            return data;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct MonUnitDataItemBase
    {
        // MonUnitDataItem() { }
        [MarshalAs( UnmanagedType.U1 )]
        public bool m_bSuccess;

        public uint m_nCoalMineId;
    }

    [StructLayout( LayoutKind.Sequential )]
    public struct MonUnitDataItem
    {
        public MonUnitDataItemBase m_baseDataItem;
        public MonUnitData m_MonUnitData;

        public byte[ ] GetByteArray( )
        {
            int length = Marshal.SizeOf( this );
            byte[ ] ba = new byte[ length ];
            IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement( ba , 0 );
            Marshal.StructureToPtr( this , ptr , true );
            return ba;
        }

        public static MonUnitDataItem ConverFromByteArray( byte[ ] ba , ref int pos )
        {
            MonUnitDataItem item = new MonUnitDataItem( );
            item.m_baseDataItem = StructConvert.PtrToStruct<MonUnitDataItemBase>( ba , ref pos );
            item.m_MonUnitData = MonUnitData.ConverFromByteArray( ba , ref pos );
            return item;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct MonUnitDataItemEx
    {
        public MonUnitDataItemBase m_baseDataItem;
        public MonUnitDataEx m_MonUnitData;

        public byte[ ] GetByteArray( )
        {
            int length = Marshal.SizeOf( this );
            byte[ ] ba = new byte[ length ];
            IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement( ba , 0 );
            Marshal.StructureToPtr( this , ptr , true );
            return ba;
        }

        public static MonUnitDataItemEx ConverFromByteArray( byte[ ] ba , ref int pos )
        {
            MonUnitDataItemEx item = new MonUnitDataItemEx( );
            item.m_baseDataItem = StructConvert.PtrToStruct<MonUnitDataItemBase>( ba , ref pos );
            item.m_MonUnitData = MonUnitDataEx.ConverFromByteArray( ba , ref pos );
            return item;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct DataAckStructBase
    {
        // DataAckStruct() { }
        public uint m_dwMethodType;

        public int m_nMethodAck;
        public uint m_dwBufSize;
        public uint m_nCoalMineId;
        public uint m_dwNumOfItems;
    }

    [StructLayout( LayoutKind.Sequential )]
    public struct DataAckStruct
    {
        public DataAckStructBase m_DataBase;
        public MonUnitDataItem[ ] m_DataItems;

        public byte[ ] GetByteArray( )
        {
            int length = Marshal.SizeOf( this );
            byte[ ] ba = new byte[ length ];

            return ba;
        }

        public static DataAckStruct ConverFromByteArray( byte[ ] ba )
        {
            int pos = 0;

            DataAckStruct st = new DataAckStruct
                                   {
                                       m_DataBase = StructConvert.PtrToStruct<DataAckStructBase>( ba , ref pos )
                                   };

            // 支持不大于 3000 个测点
            if ( st.m_DataBase.m_dwNumOfItems >= 3000 )// 600)
            {
                throw new Exception( "DataAckStruct m_dwNumOfItems>=3000" );// 600 ");
            }
            st.m_DataItems = new MonUnitDataItem[ st.m_DataBase.m_dwNumOfItems ];
            for ( int i = 0; i < st.m_DataBase.m_dwNumOfItems; i++ )
            {
                MonUnitDataItem item = new MonUnitDataItem
                                           {
                                               m_baseDataItem =
                                                   StructConvert.PtrToStruct<MonUnitDataItemBase>( ba , ref pos ) ,
                                               m_MonUnitData = MonUnitData.ConverFromByteArray( ba , ref pos )
                                           };
                st.m_DataItems[ i ] = item;
            }
            return st;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct DataAckStructEx
    {
        public DataAckStructBase m_DataBase;
        public MonUnitDataItemEx[ ] m_DataItems;

        public byte[ ] GetByteArray( )
        {
            int length = Marshal.SizeOf( this );
            byte[ ] ba = new byte[ length ];

            return ba;
        }

        public static DataAckStructEx ConverFromByteArray( byte[ ] ba )
        {
            int pos = 0;

            DataAckStructEx st = new DataAckStructEx
            {
                m_DataBase = StructConvert.PtrToStruct<DataAckStructBase>( ba , ref pos )
            };

            // 支持不大于 3000 个测点
            if ( st.m_DataBase.m_dwNumOfItems >= 3000 )// 600)
            {
                throw new Exception( "DataAckStruct m_dwNumOfItems>=3000" );// 600 ");
            }
            st.m_DataItems = new MonUnitDataItemEx[ st.m_DataBase.m_dwNumOfItems ];
            for ( int i = 0; i < st.m_DataBase.m_dwNumOfItems; i++ )
            {
                MonUnitDataItemEx item = new MonUnitDataItemEx
                {
                    m_baseDataItem =
                        StructConvert.PtrToStruct<MonUnitDataItemBase>( ba , ref pos ) ,
                    m_MonUnitData = MonUnitDataEx.ConverFromByteArray( ba , ref pos )
                };
                st.m_DataItems[ i ] = item;
            }
            return st;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct MonUnitItem
    {
        public const int SIZE_MONUNITID = 9;

        // MonUnitItem() { }

        public uint m_nCoalMineId;

        [MarshalAs( UnmanagedType.ByValTStr , SizeConst = SIZE_MONUNITID )]
        public string m_szMonUnitId;

        public byte[ ] GetByteArray( )
        {
            int length = Marshal.SizeOf( this );
            byte[ ] ba = new byte[ length ];

            return ba;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct MonUnitItemEx
    {
        public const int SIZE_MONUNITID_EX = 9;

        // MonUnitItem() { }

        public uint m_nCoalMineId;

        [MarshalAs( UnmanagedType.ByValTStr , SizeConst = SIZE_MONUNITID_EX )]
        public string m_szMonUnitId;

        public byte[ ] GetByteArray( )
        {
            int length = Marshal.SizeOf( this );
            byte[ ] ba = new byte[ length ];

            return ba;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct DataQueryStructBase
    {
        // DataQueryStruct() { }
        public uint m_dwMethodType;

        public int m_nMethodAck;

        public uint m_dwBufSize;
        public uint m_nCoalMineId;
        public uint m_dwNumOfItems;
    }

    [StructLayout( LayoutKind.Sequential )]
    public struct DataQueryStruct
    {
        // DataQueryStruct() { }
        public DataQueryStructBase baseStruct;

        public MonUnitItem[ ] m_MonUnitItems;

        public byte[ ] GetByteArray( )
        {
            int length = sizeof( int ) * 4 + sizeof( long ) + sizeof( long ) + MonUnitItem.SIZE_MONUNITID;
            byte[ ] ba = new byte[ length ];
            int pos = 0;
            Array.Copy( baseStruct.GetBytes<DataQueryStructBase>( ) , ba , baseStruct.Size( ) );

            //KWConvert.SetUIntToByteArray(m_dwMethodType, ref ba, ref pos);
            //KWConvert.SetIntToByteArray(m_nMethodAck, ref ba, ref pos);
            //KWConvert.SetUIntToByteArray(m_dwBufSize, ref ba, ref pos);
            //KWConvert.SetLongToByteArray(m_nCoalMineId, ref ba, ref pos);
            //KWConvert.SetUIntToByteArray(m_dwNumOfItems, ref ba, ref pos);
            return ba;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct DataQueryStructEx
    {
        // DataQueryStruct() { }
        public DataQueryStructBase baseStruct;

        public MonUnitItemEx[ ] m_MonUnitItems;

        public byte[ ] GetByteArray( )
        {
            int length = sizeof( int ) * 4 + sizeof( long ) + sizeof( long ) + MonUnitItemEx.SIZE_MONUNITID_EX;
            byte[ ] ba = new byte[ length ];
            int pos = 0;
            Array.Copy( baseStruct.GetBytes<DataQueryStructBase>( ) , ba , baseStruct.Size( ) );

            //KWConvert.SetUIntToByteArray(m_dwMethodType, ref ba, ref pos);
            //KWConvert.SetIntToByteArray(m_nMethodAck, ref ba, ref pos);
            //KWConvert.SetUIntToByteArray(m_dwBufSize, ref ba, ref pos);
            //KWConvert.SetLongToByteArray(m_nCoalMineId, ref ba, ref pos);
            //KWConvert.SetUIntToByteArray(m_dwNumOfItems, ref ba, ref pos);
            return ba;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct DataUpdateStructBase
    {
        // DataUpdateStruct() { }
        public uint m_dwMethodType;

        public int m_nMethodAck;
        public uint m_dwBufSize;
        public uint m_nCoalMineId;
        public uint m_dwNumOfData;
    }

    [StructLayout( LayoutKind.Sequential )]
    public struct DataUpdateStruct : IStruct<DataUpdateStruct>
    {
        public DataUpdateStructBase baseStruct;

        public MonUnitData[ ] m_MonUnitData;

        public int Count( )
        {
            return ( int )baseStruct.m_dwNumOfData;
        }

        public int Size( )
        {
            //Console.WriteLine(5 * 4 + MonUnitData.Size());
            return 68;
        }

        public uint dwBufSize( )
        {
            return ( uint )( this.Size( ) + MonUnitData.Size( ) * ( baseStruct.m_dwNumOfData - 1 ) );
        }

        public byte[ ] GetByteArray( )
        {
            //baseStruct.m_dwBufSize = dwBufSize();
            //int length =(int )baseStruct.m_dwBufSize;
            //byte[] ba = new byte[length];
            //int pos = 0;

            //Array.Copy(StructConvert.StructToByteArrar<DataUpdateStructBase>(baseStruct), 0, ba, 0, Marshal.SizeOf(baseStruct));
            //pos += Marshal.SizeOf(baseStruct);
            //for (int i = 0; i < baseStruct.m_dwNumOfData; i++)
            //{
            //    Array.Copy(StructConvert.StructToByteArrar<MonUnitData>(m_MonUnitData[i]), 0, ba, pos, MonUnitData.Size());
            //    pos += MonUnitData.Size();
            //}
            //return ba;

            return StructConvert.GetBytes<DataUpdateStruct , DataUpdateStructBase , MonUnitData>( this , baseStruct , m_MonUnitData );
        }

        public static DataUpdateStruct ConverFromByteArray( byte[ ] ba )
        {
            int pos = 0;
            DataUpdateStruct st = new DataUpdateStruct( );
            IntPtr buffer = Marshal.AllocCoTaskMem( ba.Length );
            st.baseStruct = StructConvert.PtrToStruct<DataUpdateStructBase>( buffer , ref pos );
            if ( st.baseStruct.m_dwNumOfData >= 1000 )// 600)
            {
                throw new Exception( "DefinitionAckStruct m_dwNumOfItems>= 1000 " );
            }
            st.m_MonUnitData = new MonUnitData[ st.baseStruct.m_dwNumOfData ];
            var intPtr = new IntPtr( buffer.ToInt32( ) );
            for ( int i = 0; i < st.baseStruct.m_dwNumOfData; i++ )
            {
                intPtr = new IntPtr( intPtr.ToInt32( ) + pos );
                var data = StructConvert.PtrToStruct<MonUnitData>( intPtr , ref pos );
                st.m_MonUnitData[ i ] = data;
            }
            Marshal.FreeCoTaskMem( buffer );
            return st;
        }

        public static DataUpdateStruct ConverFromByteArray0( byte[ ] ba )
        {
            int pos = 0;
            DataUpdateStruct st = new DataUpdateStruct( );
            st.baseStruct = StructConvert.PtrToStruct<DataUpdateStructBase>( ba , ref pos );
            if ( st.baseStruct.m_dwNumOfData >= 1000 )// 600)
            {
                throw new Exception( "DefinitionAckStruct m_dwNumOfItems>= 1000 " );
            }
            st.m_MonUnitData = new MonUnitData[ st.baseStruct.m_dwNumOfData ];
            for ( int i = 0; i < st.baseStruct.m_dwNumOfData; i++ )
            {
                MonUnitData item = MonUnitData.ConverFromByteArray( ba , ref pos );
                st.m_MonUnitData[ i ] = item;
            }
            return st;
        }
    };

    [StructLayout( LayoutKind.Sequential )]
    public struct DataUpdateStructEx : IStruct<DataUpdateStructEx>
    {
        public DataUpdateStructBase baseStruct;

        public MonUnitDataEx[ ] m_MonUnitData;

        public int Count( )
        {
            return ( int )baseStruct.m_dwNumOfData;
        }

        public int Size( )
        {
            //Console.WriteLine(5 * 4 + MonUnitData.Size());
            return 68;
        }

        public uint dwBufSize( )
        {
            return ( uint )( this.Size( ) + MonUnitDataEx.Size( ) * ( baseStruct.m_dwNumOfData - 1 ) );
        }

        public byte[ ] GetByteArray( )
        {
            //baseStruct.m_dwBufSize = dwBufSize();
            //int length =(int )baseStruct.m_dwBufSize;
            //byte[] ba = new byte[length];
            //int pos = 0;

            //Array.Copy(StructConvert.StructToByteArrar<DataUpdateStructBase>(baseStruct), 0, ba, 0, Marshal.SizeOf(baseStruct));
            //pos += Marshal.SizeOf(baseStruct);
            //for (int i = 0; i < baseStruct.m_dwNumOfData; i++)
            //{
            //    Array.Copy(StructConvert.StructToByteArrar<MonUnitData>(m_MonUnitData[i]), 0, ba, pos, MonUnitData.Size());
            //    pos += MonUnitData.Size();
            //}
            //return ba;

            return StructConvert.GetBytes<DataUpdateStructEx , DataUpdateStructBase , MonUnitDataEx>( this , baseStruct , m_MonUnitData );
        }

        public static DataUpdateStructEx ConverFromByteArray( byte[ ] ba )
        {
            int pos = 0;
            DataUpdateStructEx st = new DataUpdateStructEx( );
            IntPtr buffer = Marshal.AllocCoTaskMem( ba.Length );
            st.baseStruct = StructConvert.PtrToStruct<DataUpdateStructBase>( buffer , ref pos );
            if ( st.baseStruct.m_dwNumOfData >= 1000 )// 600)
            {
                throw new Exception( "DefinitionAckStruct m_dwNumOfItems>= 1000 " );
            }
            st.m_MonUnitData = new MonUnitDataEx[ st.baseStruct.m_dwNumOfData ];
            var intPtr = new IntPtr( buffer.ToInt32( ) );
            for ( int i = 0; i < st.baseStruct.m_dwNumOfData; i++ )
            {
                intPtr = new IntPtr( intPtr.ToInt32( ) + pos );
                var data = StructConvert.PtrToStruct<MonUnitDataEx>( intPtr , ref pos );
                st.m_MonUnitData[ i ] = data;
            }
            Marshal.FreeCoTaskMem( buffer );
            return st;
        }

        public static DataUpdateStructEx ConverFromByteArray0( byte[ ] ba )
        {
            int pos = 0;
            DataUpdateStructEx st = new DataUpdateStructEx( );
            st.baseStruct = StructConvert.PtrToStruct<DataUpdateStructBase>( ba , ref pos );
            if ( st.baseStruct.m_dwNumOfData >= 1000 )// 600)
            {
                throw new Exception( "DefinitionAckStruct m_dwNumOfItems>= 1000 " );
            }
            st.m_MonUnitData = new MonUnitDataEx[ st.baseStruct.m_dwNumOfData ];
            for ( int i = 0; i < st.baseStruct.m_dwNumOfData; i++ )
            {
                MonUnitDataEx item = MonUnitDataEx.ConverFromByteArray( ba , ref pos );
                st.m_MonUnitData[ i ] = item;
            }
            return st;
        }
    };
}